package cn.sylinx.common.ext.jwt;

import java.util.Date;
import java.util.Map;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

import cn.sylinx.common.ext.log.GLog;
import cn.sylinx.common.lang.Tuple;

public class JWTToken {

	public static final String DEFAULT_SECRECT = "_default_jwt_secrect_";

	/**
	 * 创建token
	 * 
	 * @param issuer
	 *            发行者
	 * @param secrect
	 *            秘钥
	 * @param headers
	 *            headers
	 * @return
	 */
	public static String createToken(String issuer, String secrect, Map<String, Object> headers) {
		return createToken(issuer, secrect, null, headers);
	}

	/**
	 * 
	 * @param issuer
	 * @param secrect
	 * @param expire
	 * @param headers
	 * @return
	 */
	public static String createToken(String issuer, String secrect, Long expire, Map<String, Object> headers) {

		String token = null;
		Date expiresAt = null;
		if (expire != null) {
			expiresAt = new Date(System.currentTimeMillis() + expire);
		}
		try {
			token = JWT.create().withIssuer(issuer).withExpiresAt(expiresAt).withHeader(headers)
					.sign(Algorithm.HMAC256(secrect));
		} catch (IllegalArgumentException | JWTCreationException e) {
			GLog.error("生成token异常", e);
		}

		return token;
	}

	/**
	 * 核实token
	 * 
	 * @param token
	 * @param args
	 * @return Tuple 0 : issuer, 1: JWT
	 */
	public static Tuple verifyToken(String token, String secrect) {

		// args[0] = secret 秘钥

		DecodedJWT jwt = null;
		try {
			jwt = JWT.decode(token);
		} catch (JWTDecodeException e) {
			GLog.error("验证token异常，token非法", e);
			return null;
		}

		try {
			JWT.require(Algorithm.HMAC256(secrect)).withIssuer(jwt.getIssuer()).build().verify(token);
		} catch (JWTVerificationException | IllegalArgumentException e) {
			GLog.error("验证token异常，token核实不通过", e);
			return null;
		}

		// 验证通过
		return Tuple.apply(jwt.getIssuer(), jwt);
	}

}
